package com.vf.common.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ChooseLocation {

    // CPU 核心数
    private static final int MAX_THREADS = Runtime.getRuntime().availableProcessors();
    // 地球半径
    private static final int R = 6371;

    /**
     * 计算两个经纬度之间的距离（Haversine 公式）
     *
     * @param lat1 第一点纬度
     * @param lon1 第一点经度
     * @param lat2 第二点纬度
     * @param lon2 第二点经度
     * @return 返回两点之间的直线距离（单位：公里）
     */
    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return R * c;
    }


    /**
     * 使用 Equirectangular Approximation 计算两点之间的直线距离（单位：公里）
     *
     * @param lat1 第一点纬度
     * @param lon1 第一点经度
     * @param lat2 第二点纬度
     * @param lon2 第二点经度
     * @return 返回两点之间的直线距离（单位：公里）
     */
    public static double approximateDistance(double lat1, double lon1, double lat2, double lon2) {
        double x = (lon2 - lon1) * Math.cos(Math.toRadians((lat1 + lat2) / 2));
        double y = (lat2 - lat1);
        return Math.sqrt(x * x + y * y) * R;
    }

    /**
     * 多线程筛选出距离指定位置 maxDistanceKm 公里以内的经纬度集合
     *
     * @param givenLocation 给定的经纬度，格式为 "经度,纬度"
     * @param locationList  数据库查询出来的经纬度集合
     * @return 返回符合条件的经纬度集合
     */
    public static List<String> filterNearbyLocations(String givenLocation, List<String> locationList, double maxDistanceKm) throws InterruptedException {
        String[] base = givenLocation.split(",");
        double baseLat = Double.parseDouble(base[1]);
        double baseLon = Double.parseDouble(base[0]);

        ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
        List<Future<String>> futures = new ArrayList<>();

        for (String location : locationList) {
            futures.add(executor.submit(() -> {
                try {
                    String[] coords = location.split(",");
                    double lat = Double.parseDouble(coords[1]);
                    double lon = Double.parseDouble(coords[0]);

                    double distance = approximateDistance(baseLat, baseLon, lat, lon);
                    if (distance <= maxDistanceKm) {
                        return location;
                    }
                } catch (Exception e) {
                    // 可记录日志或忽略异常数据
                }
                return null;
            }));
        }

        List<String> result = new ArrayList<>();
        for (Future<String> future : futures) {
            String match = null;
            try {
                match = future.get();
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
            if (match != null) {
                result.add(match);
            }
        }

        executor.shutdown();
        return result;
    }

    /**
     * 多线程筛选出距离指定位置 2 公里以内的经纬度集合
     *
     * @param givenLocation 给定的经纬度，格式为 "经度,纬度"
     * @param locationList  数据库查询出来的经纬度集合
     * @return 返回符合条件的经纬度集合
     */
    public static List<String> filterLocationsWithinRange(String givenLocation, List<String> locationList, double maxDistanceKm) throws InterruptedException, ExecutionException {
        String[] base = givenLocation.split(",");
        double baseLat = Double.parseDouble(base[1]);
        double baseLon = Double.parseDouble(base[0]);

        ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
        List<Future<String>> futures = new ArrayList<>();

        for (String location : locationList) {
            futures.add(executor.submit(() -> {
                try {
                    String[] coords = location.split(",");
                    double lat = Double.parseDouble(coords[1]);
                    double lon = Double.parseDouble(coords[0]);

                    double distance = calculateDistance(baseLat, baseLon, lat, lon);
                    if (distance <= maxDistanceKm) {
                        return location;
                    }
                } catch (Exception e) {
                    // 可记录日志或忽略异常数据
                }
                return null;
            }));
        }

        List<String> result = new ArrayList<>();
        for (Future<String> future : futures) {
            String match = future.get();
            if (match != null) {
                result.add(match);
            }
        }

        executor.shutdown();
        return result;
    }










}
